package edu.jhu.secondhome.servlet;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import edu.jhu.secondhome.database.accessors.UserAccessor;
import edu.jhu.secondhome.database.beans.User;

public class ChangePasswordServlet extends HttpServlet
{
  /**
   * 
   */
  private static final long serialVersionUID = 6865293442603761077L;

  public void init() throws ServletException
  {

  }

  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException
  {
    processRequest(req, resp);
  }

  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException
  {
    processRequest(req, resp);
  }

  public void processRequest(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException
  {
    response.setContentType("text/html;charset=UTF-8");
    ServletContext servletContext = getServletContext();
    HttpSession session = request.getSession();

    ArrayList<String> errors = new ArrayList<String>();
    request.setAttribute("errors", errors);

    Object userObj = session.getAttribute( "user" );
    User user;
    if ( userObj instanceof User )
      user = (User)userObj;
    else
    {
      errors.add( "You must be logged in to perform this action." );
      RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/index.jsp");
      dispatcher.forward(request, response);
      return;
    }

    String reg_currPassword = request.getParameter("reg_currPassword");
    String reg_newPassword = request.getParameter("reg_newPassword");
    String reg_newPassword2 = request.getParameter("reg_newPassword2");

    if ( !reg_newPassword.equals( reg_newPassword2 ) ||
        reg_newPassword.equals("") )
    {
      errors.add( "Your password values must match." );
      request.setAttribute("errors", errors);
      loadManageAccount(request, response, servletContext, user);
      return;
    }

    try
    {
      UserAccessor db = new UserAccessor();
      User dbUser = db.getUserByEmail(user.getEmail());
      
      byte[] encryptedCurrPass = User.encryptString( reg_currPassword );
      String encryptedCurrPassStr = new String( encryptedCurrPass, "UTF-8" );

      String userUTF8 = new String( dbUser.getPassword().getBytes(), "UTF-8" );
      String encryptedUTF8 = new String( encryptedCurrPassStr.getBytes(), "UTF-8" );

      // Success
      if ( userUTF8.equals( encryptedUTF8 ) )
      {
        byte[] encryptedNewPass = User.encryptString( reg_newPassword );
        String encryptedNewPassStr = new String( encryptedNewPass, "UTF-8" );

        dbUser.setPassword( encryptedNewPassStr );
        db.updateUserPassword( dbUser );
      }
      else
      {
        errors.add( "Incorrect password.  Please try again." );
      }
    } catch ( NoSuchAlgorithmException e )
    {
      e.printStackTrace();
      errors.add(e.getMessage());
    } catch ( SQLException e )
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
      errors.add(e.getMessage());
    }

    if (errors.size() > 0)
    	request.setAttribute("errors", errors);
    else
    	request.setAttribute("message", "Password Updated Successfully.");
    loadManageAccount(request, response, servletContext, user);
    return;
  }
  
  
  
  private void loadManageAccount( HttpServletRequest request,
      HttpServletResponse response, ServletContext servletContext,
      final User user ) throws ServletException, IOException
  {
	  final UserAccessor ua = new UserAccessor();
      loadAndStoreDatabaseUser(request, response, servletContext, user, ua);
	  
    if ( user.isAdmin() )
    {
      List<String> admins;
      try
      {
        admins = ua.getUserEmailsAdminStatus( true );
      } catch ( SQLException e )
      {
        log( "Couldn't retrieve admin users for account management.", e );
        admins = Collections.emptyList();
      }
      List<String> users;
      try
      {
        users = ua.getUserEmailsAdminStatus( false );
      } catch ( SQLException e )
      {
        log( "Couldn't retrieve non-admin users for account management.", e );
        users = Collections.emptyList();
      }

      if ( admins == null )
        admins = Collections.emptyList();
      if ( users == null )
        users = Collections.emptyList();
      request.setAttribute( "admins", admins );
      request.setAttribute( "users", users );
    }
    // Forward the request to manageAccount.jsp
    RequestDispatcher dispatcher = servletContext
        .getRequestDispatcher( "/manageAccount.jsp" );
    dispatcher.forward( request, response );
  }
  protected void loadAndStoreDatabaseUser( HttpServletRequest request,
	      HttpServletResponse response, ServletContext servletContext, User user,
	      UserAccessor ua )
	  {
	    User dbUser;
	    try
	    {
	      dbUser = ua.getUserByEmail( user.getEmail() );
	    } catch ( SQLException e )
	    {
	      // this should never happen since it's the currently logged in user.
	      log( "Couldn't retrieve user data for email " + user.getEmail(), e );
	      dbUser = user;
	    }
	    String cardNum = dbUser.getCreditCardNum();
	    dbUser.setPassword( "" );
	    dbUser.setCreditCardSecCode( "" );
	    if ( cardNum != null && !cardNum.isEmpty() )
	    {
	      final int length = cardNum.length();
	      if ( length > 4 )
	      {
	        dbUser.setCreditCardNum( cardNum.substring( 0, ( length - 4 ) )
	            .replaceAll( "\\d", "*" ) + cardNum.substring( length - 4 ) );
	      }
	    }
	    request.setAttribute( "dbUser", dbUser );   
	  }
}
